#include "global.h"
#include "ToolPane.h"
#include <wx/bitmap.h>
#include <map>
#include <wx/dcmemory.h>
#include <wx/filename.h>
#include <wx/msgdlg.h>
using namespace std;

static MainPane *sMainPane;
static ToolPane *sToolPane;
void SetMainPane(MainPane *p)
{
    sMainPane = p;
}
void SetToolPane(ToolPane *p)
{
    sToolPane = p;
}
SSelImage *GetSelImage()
{
    return sToolPane->GetSelImage();
}
SFrame *GetSelFrame()
{
    return sToolPane->GetSelFrame();
}

SAction *GetSelAction()
{
    return sToolPane->GetSelAction();
}

int GetSelType()
{
    return sToolPane->GetSelType();
}

map<wxString,wxBitmap*> sBmpList;
wxBitmap *FindBmp(wxString &name)
{
    map<wxString,wxBitmap*>::iterator iter = sBmpList.find(name);
    if(iter == sBmpList.end())
        return NULL;
    return iter->second;
}

wxBitmap *AddBmp(wxString &name)
{
    wxImage image;
    if(!image.LoadFile(name,wxBITMAP_TYPE_ANY))
        return NULL;
    image.InitAlpha();
    wxBitmap *pBmp = new wxBitmap(image);
    //pBmp->LoadFile(name,wxBITMAP_TYPE_ANY);
    sBmpList[name] = pBmp;
    return pBmp;
}

map<wxBitmap*,wxMemoryDC*> sMemoryDcList;
wxMemoryDC *FindMemoryDC(wxBitmap *pBmp)
{
    map<wxBitmap*,wxMemoryDC*>::iterator iter = sMemoryDcList.find(pBmp);
    if(iter == sMemoryDcList.end())
    {
        wxMemoryDC *memoryDc = new wxMemoryDC(*pBmp);
        sMemoryDcList[pBmp] = memoryDc;
        return memoryDc;
    }
    return iter->second;
}

void DrawSubBmp(wxDC &dc,wxBitmap *pBmp,wxRect &rect,wxPoint &point)
{
    if((pBmp == NULL) || !pBmp->IsOk())
        return;
    if((rect.x > pBmp->GetWidth()) || (rect.y > pBmp->GetHeight()) || (rect.x < 0) || (rect.y < 0))
        return;
    if(rect.x + rect.GetWidth() > pBmp->GetWidth())
        rect.SetWidth(pBmp->GetWidth()-rect.x);
    if(rect.y + rect.GetHeight() > pBmp->GetHeight())
        rect.SetHeight(pBmp->GetHeight()-rect.y);

    //wxMemoryDC memDc;
    //memDc.SelectObject(pBmp->GetSubBitmap(rect));
    //dc.Blit(point.x,point.y,rect.GetWidth(),rect.GetHeight(),&memDc,0,0);
    wxMemoryDC *pMomoryDc = FindMemoryDC(pBmp);
    dc.Blit(point.x,point.y,rect.GetWidth(),rect.GetHeight(),pMomoryDc,rect.x,rect.y);
}

void DrawFrame(wxDC &dc,SFrame &frame)
{
    wxBitmap *pBmp;
    SFrameImage *pFrameImage;
    for(vector<SFrameImage>::iterator i = frame.m_imageList.begin(); i != frame.m_imageList.end(); i++)
    {
        pFrameImage = &(*i);
        pBmp = FindBmp(pFrameImage->name);
        //wxMessageBox(pFrameImage->name);
        DrawSubBmp(dc,pBmp,pFrameImage->rect,pFrameImage->point);
    }
}

static wxFrame *sMainFrame;
void SetMousePos(int x,int y,int pos)
{
    wxString str;
    str<<x<<","<<y;
    sMainFrame->SetStatusText(str,pos);
}
void SetMainFrame(wxFrame *p)
{
    sMainFrame = p;
}

void GetImageList(vector<wxString> &imageList,SFrame &frame)
{
    bool add = true;
    for(vector<SFrameImage>::iterator i = frame.m_imageList.begin(); i != frame.m_imageList.end(); i++)
    {
        add = true;
        for(unsigned int pos = 0; pos < imageList.size(); pos++)
        {
            if(imageList[pos] == i->name)
            {
                add = false;
                break;
            }
        }
        if(add)
            imageList.push_back(i->name);
    }
}
void GetImageList(vector<wxString> &imageList,SAction &action)
{
    for(vector<SFrame>::iterator i = action.m_frameList.begin(); i != action.m_frameList.end(); i++)
    {
        GetImageList(imageList,*i);
    }
}
int GetImagePos(vector<wxString> &imageList,wxString &name)
{
    int i = 0;
    for(; i < (int)imageList.size(); i++)
    {
        if(imageList[i] == name)
            break;
    }
    if(i >= (int)imageList.size())
        i = -1;
    return i;
}

wxString GetFileName(wxString &path)
{
    //return path.Last
    wxFileName fileName(path);
    return fileName.GetName();
}

wxString GetPath(wxString &path)
{
    wxFileName fileName(path);
    return fileName.GetPath();
}

void ReadImageList(vector<wxString> &nameList,SFrame &frame)
{
    for(vector<SFrameImage>::iterator i = frame.m_imageList.begin(); i != frame.m_imageList.end(); i++)
    {
        i->name = GetFileName(i->name);
    }
    GetImageList(nameList,frame);
}

void ReadImageList(vector<wxString> &nameList,SAction &action)
{
    for(vector<SFrame>::iterator i = action.m_frameList.begin(); i != action.m_frameList.end(); i++)
    {
        ReadImageList(nameList,*i);
    }
}

void WriteImageList(wxFile &file,vector<wxString> &nameList)
{
    unsigned char nameSize = nameList.size();
    unsigned char nameLen;
    file.Write(&nameSize,1);
    for(unsigned char i = 0; i < nameSize; i++)
    {
        string str = nameList[i].ToStdString();
        nameLen = str.length();
        file.Write(&nameLen,sizeof(nameLen));
        file.Write(str.c_str(),nameLen);
    }
}

void WriteFrame(wxFile &file,SFrame &frame,vector<wxString> &nameList)
{
    unsigned imagePos;
    unsigned char x,y,w,h,type;
    unsigned short posX,posY;
    unsigned short fImageSzie = frame.m_imageList.size();
    file.Write(&fImageSzie,sizeof(fImageSzie));
    for(vector<SFrameImage>::iterator i = frame.m_imageList.begin(); i != frame.m_imageList.end(); i++)
    {
        imagePos = GetImagePos(nameList,GetFileName(i->name));
        x = i->rect.GetX();
        y = i->rect.GetY();
        w = i->rect.GetWidth();
        h = i->rect.GetHeight();
        type = i->type;
        posX = i->point.x;
        posY = i->point.y;
        file.Write(&imagePos,sizeof(imagePos));
        file.Write(&x,sizeof(x));
        file.Write(&y,sizeof(y));
        file.Write(&w,sizeof(w));
        file.Write(&h,sizeof(h));
        file.Write(&type,sizeof(type));
        file.Write(&posX,sizeof(posX));
        file.Write(&posY,sizeof(posY));
    }
}
void SaveFrame(SFrame &frame,wxFile &file)
{
    vector<wxString> nameList;
    ReadImageList(nameList,frame);
    WriteImageList(file,nameList);
    WriteFrame(file,frame,nameList);
}

bool ReadImageList(wxFile &file,wxString &filePath,vector<wxString> &nameList)
{
    unsigned char nameSize = nameList.size();
    file.Read(&nameSize,1);

    unsigned char nameLen;
    char name[256] = {0};
    for(unsigned char i = 0; i < nameSize; i++)
    {
        file.Read(&nameLen,sizeof(nameLen));
        file.Read(name,nameLen);
        wxString fullName = filePath+"\\"+name+".png";
        nameList.push_back(fullName);
        if(AddBmp(fullName) == NULL)
        {
            false;
        }
    }
    return true;
}

void ReadFrame(wxFile &file,vector<wxString> &nameList,SFrame &frame)
{
    unsigned imagePos;
    unsigned char x,y,w,h,type;
    unsigned short posX,posY;
    unsigned short fImageSzie;
    file.Read(&fImageSzie,sizeof(fImageSzie));
    for(unsigned short i = 0; i < fImageSzie; i++)
    {
        file.Read(&imagePos,sizeof(imagePos));
        file.Read(&x,sizeof(x));
        file.Read(&y,sizeof(y));
        file.Read(&w,sizeof(w));
        file.Read(&h,sizeof(h));
        file.Read(&type,sizeof(type));
        file.Read(&posX,sizeof(posX));
        file.Read(&posY,sizeof(posY));
        SFrameImage frameImage;
        frameImage.rect.SetX(x);
        frameImage.rect.SetY(y);
        frameImage.rect.SetWidth(w);
        frameImage.rect.SetHeight(h);
        frameImage.point.x = posX;
        frameImage.point.y = posY;
        frameImage.type = type;
        if(imagePos < nameList.size())
            frameImage.name = nameList[imagePos];
        frame.m_imageList.push_back(frameImage);
    }
}

void ReadFrame(wxFile &file,wxString &filePath,SFrame &frame)
{
    frame.m_imageList.clear();

    vector<wxString> nameList;
    if(!ReadImageList(file,filePath,nameList))
        return;
    ReadFrame(file,nameList,frame);
}

void WriteAction(wxFile &file,SAction &action,vector<wxString> &nameList)
{
    unsigned char frameNum = action.m_frameList.size();
    file.Write(&frameNum,sizeof(frameNum));
    for(vector<SFrame>::iterator i = action.m_frameList.begin(); i != action.m_frameList.end(); i++)
    {
        WriteFrame(file,*i,nameList);
    }
}
void SaveAction(SAction &action,wxFile &file)
{
    vector<wxString> nameList;
    ReadImageList(nameList,action);
    WriteImageList(file,nameList);
    WriteAction(file,action,nameList);
}

void ReadAction(wxFile &file,vector<wxString> &nameList,SAction &action)
{
    unsigned char frameNum = 0;
    file.Read(&frameNum,sizeof(frameNum));
    for(unsigned char i = 0; i < frameNum; i++)
    {
        SFrame frame;
        ReadFrame(file,nameList,frame);
        action.m_frameList.push_back(frame);
    }
}
void ReadAction(wxFile &file,wxString &filePath,SAction &action)
{
    action.m_frameList.clear();

    vector<wxString> nameList;
    if(!ReadImageList(file,filePath,nameList))
        return;
    ReadAction(file,nameList,action);
}
